#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/reg.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>	
#include <mysql/mysql.h>	

#define LAN_C 1
#define LAN_CPP 2
#define LAN_JAVA 3
#define TOTAL_LAN 3

#define MB 1048576
#define COMPILE_TIME 6
#define COMPILE_MEM 128
#define FILE_SIZE 10


char* student_id = NULL;
//记录ID
char* id = NULL;
char* language = NULL;
char* question_id = NULL;
char* ceFile = NULL;
char* output(char* path);
//编译
int compile(char* lang,char* question_id,char* student_id,char* ceFile,char* finaladdress);
//修改数据库结果
int changeresult(char* id,char* result);
int change_specific_result(char* id,char* specific_result);
MYSQL* myconnect();

int main(int argc,char *argv[]){

    //argv id,language,path,question_id,studentid
    if(argc != 6){
        printf("argv num error: %d\n",argc);
        return 0;
    }
	
    id = argv[1];//往后传
    language = argv[2];//往后传
	ceFile= argv[3];//往后传
    question_id = argv[4];//往后传
	student_id = argv[5];
	char dFile[30];
	char eFile[30];
	int kk = 0;
	for(kk =5;kk < strlen(ceFile);kk++){
		dFile[kk-5] = ceFile[kk];
	}
	strcpy(eFile,ceFile);
	char *finaladdress = strtok(dFile,".");
	char *ff = strtok(eFile,".");
    int status = compile(language,question_id,student_id,ceFile,ff);

	if (status == -1) {// system error
        //修改数据库结果为系统错误
		//changeresult system error;
		char* result = "error";
		char* introduce = "System errors";
		changeresult(id,result);
		change_specific_result(id,introduce);
        return -1;
	} else if (status != 0) {// compile error
        //修改数据库结果为编译错误
		//changeresult compile errpr;
		char* result = "compilation fail";
		
		changeresult(id,result);
        return 0;
	} else if(status == 0){// compile success
		//chageresilt Running
		//调用shell
		printf("success\n");
		char* result = "running";
		changeresult(id,result);
		char order[100]={"./start.sh"};
		strcat(order," ");
		strcat(order,argv[1]);
		strcat(order," ");
		strcat(order,argv[2]);
		strcat(order," ");
		strcat(order,finaladdress);
		strcat(order," ");
		strcat(order,argv[4]);
		strcat(order," ");
		strcat(order,argv[5]);
		//调用shell脚本
		system(order);
		return 0;
	}else{
		return 0;
	}
}


int compile(char* lang,char* question_id,char* student_id,char* ceFile,char* finaladdress){
    int time_limit = COMPILE_TIME;
	int memory_limit = COMPILE_MEM*MB;

	// compile commands
	// c and c++ must use --static to compile, otherwise the memory statistics will be incorrect
	const char *COMP_C[] = {"gcc","-Wall","-lm", "--static","Main.c","-o","Main",NULL};
	const char *COMP_CPP[] = {"g++","-Wall","-fno-asm","-lm", "--static", "-std=c++11"
		,"Main.cpp","-o","Main",NULL};
	const char *COMP_JAVA[] = {"javac","-J-Xms32m","-J-Xmx64m","-encoding","UTF-8"
		,"Main.java",NULL};

	pid_t pid = fork();
	if (pid < 0){

		return -1;
	} else if (pid != 0) {// parent
        int status;
        waitpid(pid, &status, 0);

		return status;
	} else {// child
		/* set rlimit*/
		struct rlimit lim;
		lim.rlim_cur = lim.rlim_max = time_limit;
		setrlimit(RLIMIT_CPU, &lim);

		alarm(0);
		alarm(time_limit);

	//	lim.rlim_max =
		lim.rlim_cur = memory_limit;
		setrlimit(RLIMIT_AS, &lim);

		lim.rlim_cur = lim.rlim_max = FILE_SIZE*MB;
    	setrlimit(RLIMIT_FSIZE, &lim);

		/* start compile */
		char* errorFile = (char*)malloc(20*sizeof(char));
		strcpy(errorFile,"/root/Test/");
		strcat(errorFile,question_id);
		strcat(errorFile,"/");
		strcat(errorFile,student_id);
		strcat(errorFile,"/error.txt");
		freopen(errorFile,"w",stderr);
		if(strcmp(lang,"LAN_C") == 0){
			char **c = (char**)malloc(sizeof(char*)*10);
			c[0] = (char*)malloc(sizeof(char)*20);
			strcpy(c[0],"gcc");
			c[1] = (char*)malloc(sizeof(char)*20);
			strcpy(c[1],"-o");
			c[2] = (char*)malloc(sizeof(char)*20);
			strcpy(c[2],finaladdress);
			c[3] = (char*)malloc(sizeof(char)*20);
			strcpy(c[3],ceFile);
			c[4] = NULL;
			execvp("gcc",c);
			//execvp(COMP_C[0],(char* const*)COMP_C);
		}else if(strcmp(lang,"LAN_CPP") == 0){
			char **c = (char**)malloc(sizeof(char*)*10);
			c[0] = (char*)malloc(sizeof(char)*20);
			strcpy(c[0],"g++");
			c[1] = (char*)malloc(sizeof(char)*20);
			strcpy(c[1],"-o");
			c[2] = (char*)malloc(sizeof(char)*20);
			strcpy(c[2],finaladdress);
			c[3] = (char*)malloc(sizeof(char)*20);
			strcpy(c[3],ceFile);
			c[4] = NULL;
			execvp("g++",c);		
			//execvp(COMP_CPP[0],(char* const*)COMP_CPP);
		}else if(strcmp(lang,"LAN_JAVA")){
			execvp(COMP_JAVA[0],(char* const*)COMP_JAVA);
		}else{
			printf("Nothing to do.\n");
		}
		char* error = output(errorFile);
		if(strlen(error) == 0){
			return 0;
		}else{
			return 1;
		}
		/*switch(lang){
			//第一个参数是要运行的文件，会在环境变量PATH中查找file，并执行. 要改吧
			case LAN_C: execvp(COMP_C[0],(char* const*)COMP_C); break;
			case LAN_CPP: execvp(COMP_CPP[0],(char* const*)COMP_CPP); break;
			case LAN_JAVA: execvp(COMP_JAVA[0],(char* const*)COMP_JAVA); break;
			default: std::cout << "Nothing to do.\n";
		}*/
		//exit(0);
	}
}
//获取结果
char* output(char* path){
	FILE *fp;
	char ch;
	if((fp=fopen(path,"r"))==NULL){
		printf("\nCannot open file strike any key exit!");
		return NULL;
	}
	ch=fgetc(fp);
	char output[100];
	int i = 0;
	while(ch!=EOF){
		output[i] = ch;
		i++;
		ch=fgetc(fp);
	}
	fclose(fp);
	return output;
}

int changeresult(char* id,char* result){
        printf("%s\n",result);
	MYSQL *conn_ptr = myconnect();
	char *first = (char*)malloc(100*sizeof(char));
	first="update Answer_register set question_result='";
	char *middle = "' where id='";
	char *last = "'";
	char *lastorder = (char *) malloc(strlen(result) + strlen(first)+strlen(middle)+strlen(id)+strlen(last)+10*sizeof(char));
	strcpy(lastorder,first);
	strcat(lastorder,result);
	strcat(lastorder,middle);
	strcat(lastorder,id);
	strcat(lastorder,last);
	
 	if( mysql_query(conn_ptr , lastorder))
    {
delete[] lastorder;
delete[] first;
       printf("修改数据表条目失败 %d:%s\n",mysql_errno(conn_ptr),mysql_error(conn_ptr));//打印出错误代码及详细信息
		mysql_close(conn_ptr);
        return -1;
    }
    else//成功
    {
        printf("修改数据表条目成功 Update %lurows\n",(unsigned)mysql_affected_rows(conn_ptr));//输出受影响的行数
		mysql_close(conn_ptr);
        return 1;
    }
}

int change_specific_result(char* id,char* specific_result){
	printf("specific_result\n");
        printf("%s\n",specific_result);
	MYSQL *conn_ptr = myconnect();
	char *first = (char*)malloc(100*sizeof(char));
	first="update Answer_register set question_specific_result='";
	char *middle = "' where id='";
	char *last = "'";
	char *lastorder = (char *) malloc(strlen(specific_result) + strlen(first)+strlen(middle)+strlen(id)+strlen(last)+10*sizeof(char));
	strcpy(lastorder,first);
	strcat(lastorder,specific_result);
	strcat(lastorder,middle);
	strcat(lastorder,id);
	strcat(lastorder,last);
	
 	if( mysql_query(conn_ptr , lastorder))
    {
       printf("修改数据表条目失败 %d:%s\n",mysql_errno(conn_ptr),mysql_error(conn_ptr));//打印出错误代码及详细信息
		mysql_close(conn_ptr);
delete []first;
delete []lastorder;
        return -1;
    }
    else//成功
    {
        printf("修改数据表条目成功 Update %lurows\n",(unsigned)mysql_affected_rows(conn_ptr));//输出受影响的行数
		mysql_close(conn_ptr);
delete []first;
delete []lastorder;
        return 1;
    }
}

MYSQL* myconnect(){
	MYSQL *conn_ptr;
    conn_ptr = mysql_init(NULL);//初始化
    if (!conn_ptr) {
       fprintf(stderr, "mysql_init failed\n");
       return NULL;
    } 
    conn_ptr = mysql_real_connect(conn_ptr, "47.95.1.117", "root", "123456","oj", 0, NULL, 0);//连接数据库 1则success or failed
    if (conn_ptr) {
       printf("Connection success\n");
    } else {
       printf("Connection failed\n");
    }
	return conn_ptr;
}	
